﻿using AutoMapper;
using JTTD.Common.Enum;
using JTTD.DataBase;
using JTTD.Domain.Dtos;
using JTTD.Domain.Dtos.Integral;
using JTTD.Domain.Dtos.Integral.Response;
using JTTD.Domain.Dtos.Integral.Reuqest;
using JTTD.Domain.Dtos.System.Response;
using JTTD.Domain.IService;
using JTTD.Domain.IWebApi;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebApiClient;
using JTTD.Common.Helper;
using JTTD.Domain.Dtos.Integral.Request;
using JTTD.DataBase.Model.Integral;
using JTTD.DataBase.Model.UserInfo;

namespace JTTD.Domain.Service
{
    /// <summary>
    /// 积分服务
    /// </summary>
    public class IntegralService : IIntegralService
    {
        private readonly JTTDContext _dbContext;
        private readonly IMapper _mapper;

        /// <summary>
        ///
        /// </summary>
        /// <param name="context"></param>
        /// <param name="mapper"></param>
        public IntegralService(JTTDContext context, IMapper mapper)
        {
            _dbContext = context;
            _mapper = mapper;
        }

        /// <summary>
        /// 提交账单核算积分申请
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="fileUrl"></param>
        /// <param name="amount"></param>
        /// <param name="phone"></param>
        /// <returns></returns>
        public async Task<ApiResult<bool>> CrateApply(int userId, string fileUrl, decimal amount, string phone)
        {
            try
            {
                var user = await _dbContext.UserInfos.FindAsync(userId);
                if (user == null)
                {
                    return new ApiResult<bool> { IsSuccess = false, Message = "当前用户不存在" };
                }
                var model = new DataBase.Model.Integral.IntegralApplyModel { UserId = userId, Amount = Math.Floor(amount), FileUrl = fileUrl, Phone = phone };
                _dbContext.IntegralApplyModels.Add(model);
                await _dbContext.SaveChangesAsync();
                return new ApiResult<bool> { IsSuccess = true, Message = "操作成功" };
            }
            catch (Exception ex)
            {
                return new ApiResult<bool> { IsSuccess = false, Message = "操作失败，" + ex.Message };
            }
        }

        /// <summary>
        /// 审核账单核算积分申请
        /// </summary>
        /// <param name="applyId"></param>
        /// <param name="applyState"></param>
        /// <param name="reason"></param>
        /// <returns></returns>
        public async Task<ApiResult<bool>> ExamineApply(int applyId, ApplyStateEnum applyState, string reason = null)
        {
            _dbContext.Database.BeginTransaction();
            try
            {
                var apply = await _dbContext.IntegralApplyModels.FindAsync(applyId);
                if (apply == null)
                {
                    return new ApiResult<bool> { IsSuccess = false, Message = "没有找到指定的申请记录" };
                }
                var user = await _dbContext.UserInfos.FindAsync(apply.UserId);
                if (user == null)
                {
                    return new ApiResult<bool> { IsSuccess = false, Message = "当前用户不存在" };
                }
                if (applyState == ApplyStateEnum.ExamineSuccess)
                {
                    //审核成功，判断当前时间是否有倍数积分活动
                    decimal multiple = 0;
                    var activity = await _dbContext.ActivityInfoModels.FirstOrDefaultAsync(item => item.Type == ActivityTypeEnum.MultipleIntegral && !item.IsDelete && item.IsEnable && item.StartTime <= DateTime.Now && DateTime.Now <= item.EndTime);
                    if (activity != null)
                    {
                        multiple = activity.Multiple;
                    }
                    else
                    {
                        var config = await _dbContext.ConfigInfoModels.FirstOrDefaultAsync(item => item.Key == ConfigTypeEnum.IntegralExchangeRatio);
                        if (config == null)
                        {
                            return new ApiResult<bool> { IsSuccess = false, Message = "请配置" + ConfigTypeEnum.IntegralExchangeRatio.GetDescription() };
                        }
                        multiple = Convert.ToDecimal(config.Value);
                    }
                    //判断当前用户是否是今天生日
                    if (user.Birthday.HasValue)
                    {
                        if (user.Birthday.Value.ToString("yyyyMMdd") == DateTime.Now.ToString("yyyyMMdd"))
                        {
                            var config = await _dbContext.ConfigInfoModels.FirstOrDefaultAsync(item => item.Key == ConfigTypeEnum.IntegralExchangeSpecialRatio);
                            if (config == null)
                            {
                                return new ApiResult<bool> { IsSuccess = false, Message = "请配置" + ConfigTypeEnum.IntegralExchangeSpecialRatio.GetDescription() };
                            }
                            multiple = Convert.ToDecimal(config.Value);
                        }
                    }
                    //修改审核状态
                    apply.ApplyState = ApplyStateEnum.ExamineSuccess;
                    _dbContext.IntegralApplyModels.Update(apply);
                    //修改用户积分余额
                    //user.Integral = user.Integral + Convert.ToDecimal((apply.Amount / multiple).ToString("#0.00"));
                    _dbContext.UserInfos.Update(user);
                    //添加积分收支记录
                    var record = new DataBase.Model.Integral.IntrgralRecordModel();

                    record.UserId = apply.UserId;
                    record.Type = RecordTypeEnum.Income;
                    record.Integral = Convert.ToDecimal((apply.Amount / multiple).ToString("#0.00"));
                    record.OperatingTime = DateTime.Now;
                    record.Before = await GetUserIntegral(apply.UserId);
                    record.After = record.Before + record.Integral;
                    _dbContext.IntrgralRecords.Add(record);
                    await _dbContext.SaveChangesAsync();
                }
                else
                {
                    //审核失败
                    apply.ApplyState = ApplyStateEnum.ExamineFail;
                    apply.Reason = reason;
                    _dbContext.IntegralApplyModels.Update(apply);
                    await _dbContext.SaveChangesAsync();
                }
                _dbContext.Database.CommitTransaction();
                return new ApiResult<bool> { IsSuccess = true, Message = "操作成功" };
            }
            catch (Exception ex)
            {
                _dbContext.Database.RollbackTransaction();
                return new ApiResult<bool> { IsSuccess = false, Message = "操作失败，" + ex.Message };
            }
        }

        /// <summary>
        /// 分页获取账单转积分申请
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<ApiResult<PageResult<IntegralApplyResponseDto>>> GetApplyList(SearchIntegralApplyRequestDto request, int? userId)
        {
            try
            {
                var query = _dbContext.IntegralApplyModels.Where(item => true);
                if (userId.HasValue)
                {
                    query = query.Where(item => item.UserId == userId.Value);
                }
                if (request.ApplyState.HasValue)
                {
                    query = query.Where(item => item.ApplyState == request.ApplyState.Value);
                }
                if (!string.IsNullOrWhiteSpace(request.Phone))
                {
                    query = query.Where(item => item.Phone == request.Phone.Trim());
                }
                query = query.OrderByDescending(item => item.CreateTime);
                int count = await query.CountAsync();
                if (count > 0)
                {
                    var list = await query.Skip((request.PageIndex - 1) * request.PageSize).Take(request.PageSize).ToListAsync();
                    int[] userIdArry = list.Select(item => item.UserId).ToArray();
                    var userList = await _dbContext.UserInfos.Where(item => userIdArry.Contains(item.Id)).Distinct().ToListAsync();
                    var resultList = _mapper.Map<List<IntegralApplyResponseDto>>(list);
                    foreach (var item in resultList)
                    {
                        item.UserNumber = userList.FirstOrDefault(args => args.Id == item.UserId)?.UserNumber;
                        item.UserName = userList.FirstOrDefault(args => args.Id == item.UserId)?.UserName;
                    }
                    return new ApiResult<PageResult<IntegralApplyResponseDto>>()
                    {
                        IsSuccess = true,
                        Data = new PageResult<IntegralApplyResponseDto>
                        {
                            Data = resultList,
                            PageIndex = request.PageIndex,
                            PageSize = request.PageSize,
                            TotalNum = count,
                            TotalPageNum = (count % request.PageSize) == 0 ? count / request.PageSize : count / request.PageSize + 1
                        }
                    };
                }
                else
                {
                    return new ApiResult<PageResult<IntegralApplyResponseDto>>()
                    {
                        Data = new PageResult<IntegralApplyResponseDto>()
                        {
                            PageIndex = request.PageIndex,
                            PageSize = request.PageSize,
                            Data = new List<IntegralApplyResponseDto>()
                        },
                        IsSuccess = true,
                        Message = "查询成功，暂无数据"
                    };
                }
            }
            catch (Exception ex)
            {
                return new ApiResult<PageResult<IntegralApplyResponseDto>>()
                {
                    IsSuccess = false,
                    Message = "查询失败，" + ex.Message
                };
            }
        }

        /// <summary>
        /// 分页获取用户积分收支记录
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult<PageResult<IntrgralRecordResponseDto>>> GetRecordPageList(SearchIntrgralRecordRequestDto dto)
        {
            try
            {
                var query = _dbContext.IntrgralRecords.Where(item => item.UserId == dto.UserId).OrderByDescending(item => item.OperatingTime);
                int count = await query.CountAsync();
                if (count > 0)
                {
                    var list = await query.Skip((dto.PageIndex - 1) * dto.PageSize).Take(dto.PageSize).ToListAsync();
                    return new ApiResult<PageResult<IntrgralRecordResponseDto>>()
                    {
                        IsSuccess = true,
                        Data = new PageResult<IntrgralRecordResponseDto>
                        {
                            Data = _mapper.Map<List<IntrgralRecordResponseDto>>(list),
                            PageIndex = dto.PageIndex,
                            PageSize = dto.PageSize,
                            TotalNum = count,
                            TotalPageNum = (count % dto.PageSize) == 0 ? count / dto.PageSize : count / dto.PageSize + 1
                        }
                    };
                }
                else
                {
                    return new ApiResult<PageResult<IntrgralRecordResponseDto>>()
                    {
                        Data = new PageResult<IntrgralRecordResponseDto>()
                        {
                            PageIndex = dto.PageIndex,
                            PageSize = dto.PageSize,
                            Data = new List<IntrgralRecordResponseDto>()
                        },
                        IsSuccess = true,
                        Message = "查询成功，暂无数据"
                    };
                }
            }
            catch (Exception ex)
            {
                return new ApiResult<PageResult<IntrgralRecordResponseDto>>()
                {
                    IsSuccess = false,
                    Message = "查询失败，" + ex.Message
                };
            }
        }

        /// <summary>
        /// 赠送指定用户积分
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="amount"></param>
        /// <returns></returns>
        public async Task<ApiResult<bool>> GiveIntegral(int userId, decimal amount)
        {
            _dbContext.Database.BeginTransaction();
            try
            {
                var user = await _dbContext.UserInfos.FindAsync(userId);
                if (user == null)
                {
                    return new ApiResult<bool> { IsSuccess = false, Message = "当前用户不存在" };
                }

                //user.Integral = user.Integral + amount;
               
                var record = new DataBase.Model.Integral.IntrgralRecordModel();

                record.UserId = userId;
                record.Type = RecordTypeEnum.Income;
                record.Integral = amount;
                record.OperatingTime = DateTime.Now;
                record.Before = await GetUserIntegral(userId);
                record.After = record.Before + record.Integral;
                user.Integral = record.After;
                _dbContext.UserInfos.Update(user);
                _dbContext.IntrgralRecords.Add(record);
                await _dbContext.SaveChangesAsync();
                _dbContext.Database.CommitTransaction();
                return new ApiResult<bool> { IsSuccess = true, Message = "操作成功" };
            }
            catch (Exception ex)
            {
                _dbContext.Database.RollbackTransaction();
                return new ApiResult<bool> { IsSuccess = false, Message = "操作失败，" + ex.Message };
            }
        }

        /// <summary>
        /// 扣减指定用户积分
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="amount"></param>
        /// <returns></returns>
        public async Task<ApiResult<bool>> RemoveIntegral(int userId, decimal amount)
        {
            _dbContext.Database.BeginTransaction();
            try
            {
                var user = await _dbContext.UserInfos.FindAsync(userId);
                if (user == null)
                {
                    return new ApiResult<bool> { IsSuccess = false, Message = "当前用户不存在" };
                }
                
                var record = new DataBase.Model.Integral.IntrgralRecordModel();

                record.UserId = userId;
                record.Type = RecordTypeEnum.Expenditure;
                record.Integral = amount;
                record.OperatingTime = DateTime.Now;
                record.Before = await GetUserIntegral(userId);
                record.After = record.Before - record.Integral;
                user.Integral = record.After;
                _dbContext.UserInfos.Update(user);
                _dbContext.IntrgralRecords.Add(record);
                await _dbContext.SaveChangesAsync();
                _dbContext.Database.CommitTransaction();
                return new ApiResult<bool> { IsSuccess = true, Message = "操作成功" };
            }
            catch (Exception ex)
            {
                _dbContext.Database.RollbackTransaction();
                return new ApiResult<bool> { IsSuccess = false, Message = "操作失败，" + ex.Message };
            }
        }
        
        
        /// <summary>
        /// 获取用户积分
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<decimal> GetUserIntegral(int userId)
        {
            var year = DateTime.Now.Year;
            var lastYear = DateTime.Now.Year - 1;
            var data = await _dbContext.IntrgralRecords.Where(x => x.UserId == userId && (x.OperatingTime.Year == year || x.OperatingTime.Year == lastYear)).ToListAsync();
            var integral = 0m;
            data.ForEach(x =>
            {
                if (x.Type == 0)
                {
                    integral += x.Integral;
                }
                else
                {
                    integral -= x.Integral;
                }
            });
            return integral;
        }

        /// <summary>
        /// 获取积分报告
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult<PageResult<IntrgralReportResponseDto>>> PageIntrgralReport(SearchIntrgralReportRequestDto dto)
        {
            int userId = 0;

            var year = DateTime.Now.Year;
            var lastYear = DateTime.Now.Year - 1;

            if (year <= lastYear)
            {
                return new ApiResult<PageResult<IntrgralReportResponseDto>>
                {
                    IsSuccess = false,
                    Message = "数据错误"
                };
            }

            if (dto.CteateTimeStart.HasValue && dto.CteateTimeStart.Value.Year < lastYear)
            {
                return new ApiResult<PageResult<IntrgralReportResponseDto>>
                {
                    IsSuccess = false,
                    Message = "只能查询两年内数据"
                };
            }

            if (dto.CteateTimeEnd.HasValue && dto.CteateTimeEnd.Value.Year < year)
            {
                return new ApiResult<PageResult<IntrgralReportResponseDto>>
                {
                    IsSuccess = false,
                    Message = "只能查询两年内数据"
                };
            }
            UserInfoModel user = new UserInfoModel();
            if (!string.IsNullOrEmpty(dto.PhoneNumber))
            {
                user = await _dbContext.UserInfos.FirstOrDefaultAsync(x => x.Phone == dto.PhoneNumber);
                if (user == null || user.Id <= 0)
                {
                    return new ApiResult<PageResult<IntrgralReportResponseDto>>
                    {
                        IsSuccess = false,
                        Message = "查询用户失败"
                    };
                }
                userId = user.Id;
            }

            var query = _dbContext.IntrgralRecords.Where(x => x.OperatingTime.Year == year || x.OperatingTime.Year == lastYear);

            if (userId > 0)
                query = query.Where(x => x.UserId == userId);

            if (dto.CteateTimeStart.HasValue)
                query = query.Where(x => x.OperatingTime >= dto.CteateTimeStart.Value);

            if (dto.CteateTimeEnd.HasValue)
                query = query.Where(x => x.OperatingTime <= dto.CteateTimeEnd.Value);

            query = query.OrderByDescending(item => item.OperatingTime);
            int count = await query.CountAsync();

            if (count > 0)
            {
                var list = await query.Skip((dto.PageIndex - 1) * dto.PageSize).Take(dto.PageSize).ToListAsync();
                List<IntrgralReportResponseDto> data = new List<IntrgralReportResponseDto>();
                foreach (var item in list)
                {
                    IntrgralReportResponseDto info = new IntrgralReportResponseDto();
                    info.After = item.After;
                    if (userId > 0)
                    {
                        info.PhoneNumber = user.Phone;
                        info.UserNumber = user.UserNumber;
                        info.UserId = userId;
                    }
                    else
                    {
                        var userItem = await _dbContext.UserInfos.FirstOrDefaultAsync(x => x.Id == item.UserId);
                        info.PhoneNumber = userItem.Phone;
                        info.UserNumber = userItem.UserNumber;
                        info.UserId = info.UserId;
                    }
                    info.IntegralValue = item.Integral;
                    info.Before = item.Before;
                    info.TypeStr = item.Type.GetDescription();
                    info.CteateTime = item.OperatingTime;
                    data.Add(info);
                }

                return new ApiResult<PageResult<IntrgralReportResponseDto>>()
                {
                    IsSuccess = true,
                    Data = new PageResult<IntrgralReportResponseDto>
                    {
                        Data = data,
                        PageIndex = dto.PageIndex,
                        PageSize = dto.PageSize,
                        TotalNum = count,
                        TotalPageNum = (count % dto.PageSize) == 0 ? count / dto.PageSize : count / dto.PageSize + 1
                    }
                };
            }
            else
            {
                return new ApiResult<PageResult<IntrgralReportResponseDto>>
                {
                    IsSuccess = false,
                    Message = "查询数据为空"
                };
            }

        }


        /// <summary>
        /// 获取积分报告
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<List<IntrgralReportExportResponseDto>> GetIntrgralReportExportList(SearchIntrgralReportRequestDto dto)
        {
            int userId = 0;

            var year = DateTime.Now.Year;
            var lastYear = DateTime.Now.Year - 1;

            if (year <= lastYear)
            {
                throw new Exception("参数错误");
            }

            if (dto.CteateTimeStart.HasValue && dto.CteateTimeStart.Value.Year < lastYear)
            {
                throw new Exception("只能导出两年内数据");
            }

            if (dto.CteateTimeEnd.HasValue && dto.CteateTimeEnd.Value.Year < year)
            {
                throw new Exception("只能导出两年内数据");
            }
            UserInfoModel user = new UserInfoModel();
            if (!string.IsNullOrEmpty(dto.PhoneNumber))
            {
                user = await _dbContext.UserInfos.FirstOrDefaultAsync(x => x.Phone == dto.PhoneNumber);
                if (user == null || user.Id <= 0)
                {
                    throw new Exception("没有找到指定用户");
                }
                userId = user.Id;
            }

            var query = _dbContext.IntrgralRecords.Where(x => x.OperatingTime.Year == year || x.OperatingTime.Year == lastYear);

            if (userId > 0)
                query = query.Where(x => x.UserId == userId);

            if (dto.CteateTimeStart.HasValue)
                query = query.Where(x => x.OperatingTime >= dto.CteateTimeStart.Value);

            if (dto.CteateTimeEnd.HasValue)
                query = query.Where(x => x.OperatingTime <= dto.CteateTimeEnd.Value);

            query = query.OrderByDescending(item => item.OperatingTime);
            var list = await query.ToListAsync();
            List<IntrgralReportExportResponseDto> data = new List<IntrgralReportExportResponseDto>();
            if(list!=null&&list.Any())
            {
                foreach (var item in list)
                {
                    try
                    {
                        IntrgralReportExportResponseDto info = new IntrgralReportExportResponseDto();
                        info.After = item.After;
                        if (userId > 0)
                        {
                            info.PhoneNumber = user.Phone;
                            info.UserNumber = user.UserNumber;

                        }
                        else
                        {
                            var userItem = await _dbContext.UserInfos.FirstOrDefaultAsync(x => x.Id == item.UserId);
                            info.PhoneNumber = userItem.Phone;
                            info.UserNumber = userItem.UserNumber;

                        }
                        info.IntegralValue = item.Integral;
                        info.Before = item.Before;
                        info.TypeStr = item.Type.GetDescription();
                        info.CteateTime = item.OperatingTime.ToString("yyyy-MM-dd HH:mm:ss");
                        data.Add(info);
                    }
                    catch (Exception ex) { 
                    
                    }

                }
            }
            return data;

        }




        public async Task<ApiResult<bool>> Fix()
        {
            var query = await _dbContext.IntrgralRecords.ToListAsync();

            var userIdlist = query.GroupBy(x => x.UserId).Select(x => x.Key).ToList();
            foreach (var userId in userIdlist)
            {
                var userInt = query.Where(x => x.UserId == userId).OrderByDescending(x => x.OperatingTime).ToList();
                var userNow = await GetUserIntegral(userId);
                foreach (var item in userInt)
                {
                    IntrgralRecordCopyModel copyModel = new IntrgralRecordCopyModel();
                    copyModel.Id = item.Id;
                    copyModel.Integral = item.Integral;
                    copyModel.OperatingTime = item.OperatingTime;
                    copyModel.Type = item.Type;
                    copyModel.UserId = item.UserId;
                    copyModel.After = userNow;
                    if (item.Type == 0)
                    {
                        copyModel.Before = userNow - item.Integral;
                        userNow = copyModel.Before;
                    }
                    else
                    {
                        copyModel.Before = userNow + item.Integral;
                        userNow = copyModel.Before;
                    }
                    _dbContext.intrgralRecordCopyModels.Add(copyModel);
                    await _dbContext.SaveChangesAsync();
                }
            }
            return new ApiResult<bool>
            {
                IsSuccess = true,
                Data = true
            };
        }
    }
}